class WebSocketUtility {
    ws: WebSocket
    url: string
    heartbeatTimer: any
    heartbeatInterval: number
    messageHandler: Function
    errorHandler: Function
    closeHandler: Function
    openHandler: Function
    heartbeatHandler: Function
    RemainingReconnectTimes: number = 3 // remaining reconnect times
    private reconnectTimer: any = null
    private baseReconnectDelay: number = 1000 // 初始重连延迟1秒
    private maxReconnectDelay: number = 30000 // 最大重连延迟30秒
    private currentReconnectDelay: number = this.baseReconnectDelay

    constructor(
        url,
        messageHandler,
        errorHandler,
        closeHandler,
        openHandler,
        heartbeatHandler?,
        heartbeatInterval = 30 * 1000,
        RemainingReconnectTimes = 3
    ) {
        this.RemainingReconnectTimes = RemainingReconnectTimes
        this.heartbeatInterval = heartbeatInterval
        this.url = url
        this.messageHandler = messageHandler
        this.errorHandler = errorHandler
        this.closeHandler = closeHandler
        this.openHandler = openHandler
        this.heartbeatHandler = heartbeatHandler
        this.ws = this.initWebSocket()
    }

    private initWebSocket() {
        const ws = new WebSocket(this.url)
    
        ws.onopen = () => {
            this.currentReconnectDelay = this.baseReconnectDelay // 重置重连延迟
            this.openHandler && this.openHandler()
            this.startInterval(this.heartbeatHandler)
        }

        ws.onmessage = (event) => {
            if (event.data === 'pong') {
                this.resetInterval()
                return
            }
            this.messageHandler(event.data)
        }

        ws.onerror = (event) => {
            this.stopInterval()
            this.errorHandler && this.errorHandler(event)
            this.scheduleReconnect()
        }

        ws.onclose = (event) => {
            this.stopInterval()
            this.closeHandler && this.closeHandler(event)
            this.scheduleReconnect()
        }
        return ws
    }

    static getWebSocketUrl(url: string): string {
        return url
    }

    private scheduleReconnect() {
        if (this.RemainingReconnectTimes <= 0) {
            console.log('Max reconnection attempts reached')
            return
        }

        // 清除可能存在的重连定时器
        if (this.reconnectTimer) {
            clearTimeout(this.reconnectTimer)
        }

        this.reconnectTimer = setTimeout(() => {
            this.RemainingReconnectTimes--
            console.log(`Attempting to reconnect... (${this.RemainingReconnectTimes} attempts remaining)`)
            
            this.ws?.close()
            this.initWebSocket()
            
            // 使用指数退避策略
            this.currentReconnectDelay = Math.min(
                this.currentReconnectDelay * 2,
                this.maxReconnectDelay
            )
        }, this.currentReconnectDelay)
    }

    startInterval(cb: Function) {
        this.heartbeatTimer = setInterval(() => {
            if (this.ws.readyState === 1) {
                this.send('ping')
                cb && cb()
            }
        }, this.heartbeatInterval)
    }

    stopInterval() {
        if (this.heartbeatTimer) {
            clearInterval(this.heartbeatTimer)
            this.heartbeatTimer = null
        }
    }

    resetInterval() {
        this.stopInterval()
        this.startInterval(this.heartbeatHandler)
    }

    send(msg) {
        if (this.ws.readyState === 1) {
            this.ws.send(msg)
        }
    }

    readyState() {
        return this.ws.readyState
    }

    // 新增：主动断开连接的方法
    disconnect() {
        this.RemainingReconnectTimes = 0 // 防止重连
        if (this.reconnectTimer) {
            clearTimeout(this.reconnectTimer)
        }
        this.stopInterval()
        this.ws?.close()
    }
}

export default WebSocketUtility
